package utilities;


import core.ObjectePersistent;
import core.ObjectePersistentFctr;

import java.util.*;
import java.sql.*;
import java.beans.*;
import java.lang.reflect.*;

/**
 * Created with IntelliJ IDEA.
 * User: Jordi
 * Date: 3/01/13
 * Time: 18:20
 * To change this template use File | Settings | File Templates.
 */
public class GuardarInformacio implements GuardarInfo, java.io.Serializable, Cloneable {

    public GuardarInformacio () {
        if (Boolean.getBoolean("debug-lwpf") || Boolean.getBoolean("debug-" + getClass().getName())) {
            setDebug(true);
        }
    }
    protected int contadorBajas = 0;
    protected int contadorAltas = 0;
    protected int contadorModificaciones = 0;
    protected List objetosEliminados = null;
    protected List objetosCreados = null;
    protected List objetosModificados = null;
    protected List generadasSQL = null;
    protected ObjectePersistentFctr peticion = null;
    protected String nombreTablaCompleto = null;
    protected String modificacionCatalogo = null;
    protected String modificacionEsquema = null;
    protected String tablaModificada = null;
    protected Object[] ARG_LECT_VACIO = new Object[0];
    protected boolean debug = false;
    protected Throwable erroresDetectados = null;
    protected boolean excepcionEnObjectListVacio = false;
    protected void init() throws SQLException {
        contadorBajas = 0;
        contadorAltas = 0;
        contadorModificaciones = 0;
        if (peticion.getMetadatos() == null) {
            peticion.rellenarMetadatos();
        }
        modificacionCatalogo = this.peticion.getCatalogo();
        modificacionEsquema = this.peticion.getEsquema();
        tablaModificada = this.peticion.getTabla();
        erroresDetectados = null;
        if (objetosEliminados == null) {
            objetosEliminados = new ArrayList();
        }
        if (objetosCreados == null) {
            objetosCreados = new ArrayList();
        }
        if (objetosModificados == null) {
            objetosModificados = new ArrayList();
        }
        if (tablaModificada == null) {
            throw new SQLException("Taula inexistent");
        }
        nombreTablaCompleto = tablaModificada;
        if (modificacionEsquema != null) {
            nombreTablaCompleto = modificacionEsquema + "." + nombreTablaCompleto;
            if (modificacionCatalogo != null) {
                nombreTablaCompleto = modificacionCatalogo + "." + nombreTablaCompleto;
            }
        }
    }
    @Override
    public boolean guardarInfo(ObjectePersistentFctr peticion) {
        if (peticion.isSoloLectura()) {
            setErroresDetectados(new SQLException("Sols lectura"));
            return false;
        }
        this.peticion = peticion;
        try {
            this.init();
        } catch (SQLException sqle) {
            setErroresDetectados(sqle);
            return false;
        }
        boolean completado = true;
        boolean vacio = false;
        if (debug) {
            System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this + "::writeData()::peticion.getObjectList()                    =================== " + peticion.getListaObjetos());
        }
        if (peticion.getListaObjetos() == null || peticion.getListaObjetos().isEmpty()) {
            vacio = true;
        }
        objetosEliminados = peticion.getObjetosEliminados();
        if (debug) {
            System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this + "::writeData()::objetosEliminados                    =================== " + objetosEliminados);
        }
        if ((objetosEliminados == null || objetosEliminados.isEmpty()) && vacio) {
            if (excepcionEnObjectListVacio) {
                setErroresDetectados(new SQLException("No hi ha informació per a guardar"));
                return false;
            }
            return true;
        }
        if (peticion.getDatosModificacionSequence() != null) {
            Iterator it = peticion.getListaObjetos().iterator();
            while (it.hasNext()) {
                ObjectePersistent objectePersistent = (ObjectePersistent) it.next();
                if (debug) {
                    System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this + "::writeData()::objectePersistent                            =================== " + objectePersistent);
                }
                if (objectePersistent.getEstatPersistencia() == ObjectePersistent.ESBORRAT && objectePersistent.getValorsOriginals() != null &&
                        objectePersistent.getValorsOriginals().getComptadorCamps() > 0) {
                    objetosEliminados.add(objectePersistent);
                } else if (objectePersistent.getEstatPersistencia() == ObjectePersistent.GUARDAT && objectePersistent.getValorsOriginals() !=
                        null && objectePersistent.getValorsOriginals().getComptadorCamps() > 0) {
                    objetosModificados.add(objectePersistent);
                } else if (objectePersistent.getEstatPersistencia() == ObjectePersistent.CREAT && objectePersistent.getValorsOriginals() == null ||
                        objectePersistent.getValorsOriginals().getComptadorCamps() < 1) {
                    objetosCreados.add(objectePersistent);
                }
            }
            for (int i = 0; i < peticion.getDatosModificacionSequence().length; i++) {
                if (peticion.getDatosModificacionSequence(i) == ObjectePersistentFctr.DATOS_MODIFICACION_SEQUENCE_DELETE) {
                    eliminaObjetos();
                } else if (peticion.getDatosModificacionSequence(i) == ObjectePersistentFctr.DATOS_MODIFICACION_SEQUENCE_UPDATE) {
                    almacenaObjetos();
                } else if (peticion.getDatosModificacionSequence(i) == ObjectePersistentFctr.DATOS_MODIFICACION_SEQUENCE_INSERT) {
                    creaObjetos();
                }
            }
        } else {
            peticion.getListaObjetos().addAll(objetosEliminados);
            Iterator it = peticion.getListaObjetos().iterator();
            while (it.hasNext()) {
                ObjectePersistent objectePersistent = (ObjectePersistent) it.next();
                if (debug) {
                    System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this + "::writeData()::objectePersistent                            =================== " + objectePersistent);
                }
                if (objectePersistent.getEstatPersistencia() == ObjectePersistent.ESBORRAT && objectePersistent.getValorsOriginals() != null &&
                        objectePersistent.getValorsOriginals().getComptadorCamps() > 0) {
                    if (!eliminaObjeto(objectePersistent)) {
                        return false;
                    }
                } else if (objectePersistent.getEstatPersistencia() == ObjectePersistent.GUARDAT && objectePersistent.getValorsOriginals() !=
                        null && objectePersistent.getValorsOriginals().getComptadorCamps() > 0) {
                    if (!almacenarObjeto(objectePersistent)) {
                        return false;
                    }
                } else if (objectePersistent.getEstatPersistencia() == ObjectePersistent.CREAT && objectePersistent.getValorsOriginals() == null ||
                        objectePersistent.getValorsOriginals().getComptadorCamps() < 1) {
                    if (!creaObjeto(objectePersistent)) {
                        return false;
                    }
                } else if (objectePersistent.getEstatPersistencia() == ObjectePersistent.ORIGINAL) {
// no hace nada
                } else {
                    setErroresDetectados(new SQLException("Invalido PersistentState"));
                    return false;
                }
            }
        }
        return completado;
    }
    protected boolean eliminaObjetos() {
        if (objetosEliminados.isEmpty()) {
            return true;
        }
        Iterator iter = objetosEliminados.iterator();
        while (iter.hasNext()) {
            ObjectePersistent objectePersistent = (ObjectePersistent) iter.next();
            if (!eliminaObjeto(objectePersistent)) {
                return false;
            }
        }
        return true;
    }
    protected boolean almacenaObjetos() {
        Iterator iter = objetosModificados.iterator();
        while (iter.hasNext()) {
            ObjectePersistent objectePersistent = (ObjectePersistent) iter.next();
            if (!almacenarObjeto(objectePersistent)) {
                return false;
            }
        }
        return true;
    }
    protected boolean creaObjetos() {
        Iterator iter = objetosCreados.iterator();
        while (iter.hasNext()) {
            ObjectePersistent objectePersistent = (ObjectePersistent) iter.next();
            if (!creaObjeto(objectePersistent)) {
                return false;
            }
        }
        return true;
    }
    @SuppressWarnings("static-access")
    protected boolean eliminaObjeto(ObjectePersistent objectePersistent) {
        String nombreCampo = null;
        Collection colParm = new ArrayList();
        StringBuffer sql = new StringBuffer("DELETE FROM ");
        try {
            sql.append(nombreTablaCompleto);
            sql.append(" WHERE ");
/* Siempre se deben usar columnas con PrimaryKeys en clausulas WHERE */
            List pk = peticion.getPrimaryKey(modificacionCatalogo, modificacionEsquema, tablaModificada);
            Iterator iter = pk.iterator();
            while (iter.hasNext()) {
                String nombreColumna = (String) iter.next(); // nombre de columna completo
                nombreCampo = (String) peticion.getMapping().get(nombreColumna);
                int idx = peticion.getMetadatos().getIndiceColumnaPorNombreCampo(nombreCampo);
                Method leerMethod = peticion.getMetadatos().getLeerMethod(idx);
                Object valorOriginal = objectePersistent.getValorOriginal(nombreCampo);
                if (valorOriginal == null) {
                    sql.append(nombreColumna).append(" IS NULL AND ");
                } else {
                    sql.append(nombreColumna).append(" = ? AND ");
                    colParm.add(valorOriginal);
                }
            }
            if (peticion.getOptimisticLock() == ObjectePersistentFctr.KEY_COLUMNS) { /* built de nuevo */
/* Para DELETE se deben poner iguales KEY_AND_MODIFIED_COLUMNS y KEY_AND_UPDATEBLE_COLUMNS: se debe incluir todas las
columnas de tabla en la cláusula WHERE */
            } else if (peticion.getOptimisticLock() == peticion.KEY_AND_MODIFIED_COLUMNS || peticion.getOptimisticLock() ==
                    ObjectePersistentFctr.KEY_AND_UPDATEBLE_COLUMNS) {
                for (int i = 1; i <= peticion.getMetadatos().getContadorColumna(); i++) {
                    String catalogo = peticion.getMetadatos().getNomCataleg(i);
                    String esquema = peticion.getMetadatos().getNomEsquema(i);
                    String tabla = peticion.getMetadatos().getNomTaula(i);
                    if (modificacionCatalogo != null) {
                        if (!modificacionCatalogo.equals(catalogo)) {
                            continue;
                        }
                    }
                    if (modificacionEsquema != null) {
                        if (!modificacionEsquema.equals(esquema)) {
                            continue;
                        }
                    }
                    if (tablaModificada != null) {
                        if (!tablaModificada.equals(tabla)) {
                            continue;
                        }
                    }
                    String nombreColumna = peticion.getMetadatos().getColumnaNomComplert(i);
                    if (sql.indexOf(nombreColumna) > -1) {
                        continue;// esta es una columna tipo PK
                    }
                    if (!peticion.getMetadatos().isGrabable(i) || peticion.getMetadatos().isSolsLectura(i)) {
                        continue;
                    }
                    nombreCampo = peticion.getMetadatos().getNomCamp(i);
                    try {
                        Object valor = leerValor(objectePersistent, peticion.getMetadatos().getLeerMethod(i));
                        Object valorOriginal = objectePersistent.getValorOriginal(nombreCampo);
                        if (valorOriginal == null) {
                            sql.append(nombreColumna).append(" IS NULL AND ");
                        } else {
                            sql.append(nombreColumna).append(" = ? AND ");
                            colParm.add(valorOriginal);
                        }
                    } catch (Throwable t) {
                        throw new SQLException(t.getMessage());
                    }
                }
            } else {
                throw new SQLException("Ajuste para bloqueo optimo (Optimistic Lock) invalido");
            }
            int sqlLong = sql.length();
            sql = sql.delete(sqlLong - 5, sqlLong - 1);
            if (peticion.isGenerarSoloSQL()) {
                if (generadasSQL == null) {
                    generadasSQL = new ArrayList();
                }
                Object[] nota = new Object[2];
                nota[0] = sql.toString();
                nota[1] = colParm.toArray();
                generadasSQL.add(nota);
            } else {
                int filasAfectadas = peticion.getUtilitats().ejecutar(sql.toString(), colParm);
                if (peticion.isThrowOptimisticLockDeleteException() && filasAfectadas != 1) {
                    return false;
                }
                setContadorBajas(contadorBajas + filasAfectadas);
            }
        } catch (SQLException sqlEx) {
            if (debug) {
                System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this + "::eliminaObjeto::Excepcion in                        eliminaObjeto: " + sqlEx);
            }
            setErroresDetectados(sqlEx);
            sqlEx.printStackTrace();
            return manejadorExcepcion(objectePersistent, sql.toString(), colParm, sqlEx);
        }
        return true;
    }
    @SuppressWarnings("static-access")
    protected boolean almacenarObjeto(ObjectePersistent objectePersistent) {
        String nombreCampo = null;
        StringBuffer sql = new StringBuffer("UPDATE ");
        List listParms = new ArrayList();
        if (debug) {
            System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this + "::almacenarObjeto                    ===================");
        }
        try {
            sql.append(nombreTablaCompleto).append(" SET ");
            for (int i = 1; i <= peticion.getMetadatos().getContadorColumna(); i++) {
                String catalogo = peticion.getMetadatos().getNomCataleg(i);
                String esquema = peticion.getMetadatos().getNomEsquema(i);
                String tabla = peticion.getMetadatos().getNomTaula(i);
                if (modificacionCatalogo != null) {
                    if (!modificacionCatalogo.equals(catalogo)) {
                        continue;
                    }
                }
                if (modificacionEsquema != null) {
                    if (!modificacionEsquema.equals(esquema)) {
                        continue;
                    }
                }
                if (tablaModificada != null) {
                    if (!tablaModificada.equals(tabla)) {
                        continue;
                    }
                }
                if (!peticion.getMetadatos().isGrabable(i) || peticion.getMetadatos().isSolsLectura(i)) {
                    continue;
                }
                String nombreColumna = null;
                if (peticion.isNoNombreColumnaCompleto()) {
                    nombreColumna = peticion.getMetadatos().getNomColumna(i);
                } else {
                    nombreColumna = peticion.getMetadatos().getColumnaNomComplert(i);
                }
                nombreCampo = peticion.getMetadatos().getNomCamp(i);
                Object valor = leerValor(objectePersistent, peticion.getMetadatos().getLeerMethod(i));
                Object valorOriginal = objectePersistent.getValorOriginal(nombreCampo);
                if (debug) {
                    System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this +
                            "::almacenarObjeto::nombreCampo: " + nombreCampo + " value: " + valor + " origValue: " + valorOriginal + " isWritable: " +
                            peticion.getMetadatos().isGrabable(i) + " isReadOnly: " + peticion.getMetadatos().isSolsLectura(i) + " ===================");
                }
                if (valorOriginal == null) {
                    if (valor == null) {
                        continue; // mismo valor - no se debe incluir en la actualización (update)
                    } else {
                        sql.append(nombreColumna).append(" = ?, ");
                        listParms.add(valor);
                    }
                } else {
                    if (valor == null) {
                        sql.append(nombreColumna).append(" = NULL, ");
                    } else {
                        if (!valorOriginal.equals(valor)) {
                            sql.append(nombreColumna).append(" = ?, ");
                            listParms.add(valor);
                        } else {
                            continue;
                        }
                    }
                }
            }
            int idx = sql.lastIndexOf(", ");
            if (idx > -1) {
                sql = sql.delete(idx, idx + 2);
            } else { // datos de ninguna columna modificada
                objectePersistent.setEstatPersistencia(ObjectePersistent.ORIGINAL);
                return true;
            }
/* Construir WHERE */
/* Siempre se deben usar columnas tipo PrimaryKeys en clausulas WHERE */
            StringBuffer where = new StringBuffer(" WHERE ");
            List pk = peticion.getPrimaryKey(modificacionCatalogo, modificacionEsquema, tablaModificada);
            if (debug) {
                System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this + "::almacenarObjeto::pk: " + pk + "                        modificacionEsquema: " + modificacionEsquema + " tablaModificada: " + tablaModificada);
            }
            Iterator iter = pk.iterator();
            while (iter.hasNext()) {
                String nombreColumna = (String) iter.next();
                nombreCampo = (String) peticion.getMapping().get(nombreColumna);
                if (debug) {
                    System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this +
                            "::almacenarObjeto::nombreColumna: " + nombreColumna + " nombreCampo: " + nombreCampo);
                }
                int index = peticion.getMetadatos().getIndiceColumnaPorNombreCampo(nombreCampo);
                Object valorOriginal = objectePersistent.getValorOriginal(nombreCampo);
                if (valorOriginal == null) {
                    where.append(nombreColumna).append(" IS NULL AND ");
                } else {
                    where.append(nombreColumna).append(" = ? AND ");
                    listParms.add(valorOriginal);
                }
            }
            if (peticion.getOptimisticLock() == ObjectePersistentFctr.KEY_COLUMNS) {
                idx = where.lastIndexOf(" AND ");
                where = where.delete(idx + 1, idx + 5);
            }
            if (peticion.getOptimisticLock() == ObjectePersistentFctr.KEY_COLUMNS) {
// ... construir de nuevo
            } else if (peticion.getOptimisticLock() == ObjectePersistentFctr.KEY_AND_MODIFIED_COLUMNS) {
                for (int i = 1; i <= peticion.getMetadatos().getContadorColumna(); i++) {
                    String catalogo = peticion.getMetadatos().getNomCataleg(i);
                    String esquema = peticion.getMetadatos().getNomEsquema(i);
                    String tabla = peticion.getMetadatos().getNomTaula(i);
                    if (modificacionCatalogo != null) {
                        if (!modificacionCatalogo.equals(catalogo)) {
                            continue;
                        }
                    }
                    if (modificacionEsquema != null) {
                        if (!modificacionEsquema.equals(esquema)) {
                            continue;
                        }
                    }
                    if (tablaModificada != null) {
                        if (!tablaModificada.equals(tabla)) {
                            continue;
                        }
                    }
                    String nombreColumna = peticion.getMetadatos().getColumnaNomComplert(i);
                    if (where.indexOf(nombreColumna) > -1) {
                        continue;// esta es una columna tipo PK
                    }
                    if (!peticion.getMetadatos().isGrabable(i) || peticion.getMetadatos().isSolsLectura(i)) {
                        continue;
                    }
                    nombreCampo = peticion.getMetadatos().getNomCamp(i);
                    Object valor = leerValor(objectePersistent, peticion.getMetadatos().getLeerMethod(i));
                    Object valorOriginal = objectePersistent.getValorOriginal(nombreCampo);
                    if (valorOriginal == null) {
                        if (valor == null) {
                            continue;
                        } else {
                            where.append(nombreColumna).append(" IS NULL AND ");
                        }
                    } else {
                        if (valor == null) {
                            where.append(nombreColumna).append(" = ? AND ");
                            listParms.add(valorOriginal);
                        } else {
                            if (valorOriginal.equals(valor)) {
                                continue;
                            } else {
                                where.append(nombreColumna).append(" = ? AND ");
                                listParms.add(valorOriginal);
                            }
                        }
                    }
                }
            } else if (peticion.getOptimisticLock() == ObjectePersistentFctr.KEY_AND_UPDATEBLE_COLUMNS) {
                for (int i = 1; i <= peticion.getMetadatos().getContadorColumna(); i++) {
                    String catalogo = peticion.getMetadatos().getNomCataleg(i);
                    String esquema = peticion.getMetadatos().getNomEsquema(i);
                    String tabla = peticion.getMetadatos().getNomTaula(i);
                    if (modificacionCatalogo != null) {
                        if (!modificacionCatalogo.equals(catalogo)) {
                            continue;
                        }
                    }
                    if (modificacionEsquema != null) {
                        if (!modificacionEsquema.equals(esquema)) {
                            continue;
                        }
                    }
                    if (tablaModificada != null) {
                        if (!tablaModificada.equals(tabla)) {
                            continue;
                        }
                    }
                    String nombreColumna = peticion.getMetadatos().getColumnaNomComplert(i);
                    if (where.indexOf(nombreColumna) > -1) {
                        continue; // esta es una columna tipo PK
                    }
                    if (!peticion.getMetadatos().isGrabable(i) || peticion.getMetadatos().isSolsLectura(i)) {
                        continue;
                    }
                    nombreCampo = peticion.getMetadatos().getNomCamp(i);
                    Object valor = leerValor(objectePersistent, peticion.getMetadatos().getLeerMethod(i));
                    Object valorOriginal = objectePersistent.getValorOriginal(nombreCampo);
                    if (valorOriginal == null) {
                        where.append(nombreColumna).append(" IS NULL AND ");
                    } else {
                        where.append(nombreColumna).append(" = ? AND ");
                        listParms.add(valorOriginal);
                    }
                }
            } else {
                throw new SQLException("Ajuste para bloqueo optimo (Optimistic Lock) invalido");
            }
            if (debug) {
                System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this + "::almacenarObjeto::where 1 : " +
                        where);
            }
            if (debug) {
                System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this +
                        "::almacenarObjeto::peticion.KEY_COLUMNS 1 : " + peticion.KEY_COLUMNS);
            }
            if (peticion.getOptimisticLock() != ObjectePersistentFctr.KEY_COLUMNS) {
                idx = where.length();
                where = where.delete(idx - 5, idx - 1);
            }
            if (debug) {
                System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this + "::almacenarObjeto::where 2 : " +
                        where);
            }
            sql.append(where);
            if (debug) {
                System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this +
                        "::almacenarObjeto::almacenarObjeto: " + sql + "; listParms: " + listParms);
            }
            if (peticion.isGenerarSoloSQL()) {
                if (generadasSQL == null) {
                    generadasSQL = new ArrayList();
                }
                Object[] nota = new Object[2];
                nota[0] = sql.toString();
                nota[1] = listParms.toArray();
                generadasSQL.add(nota);
            } else {
                int filasAfectadas = peticion.getUtilitats().ejecutar(sql.toString(), listParms);
                if (peticion.isThrowOptimisticLockUpdateException() && filasAfectadas != 1) {
                    if (debug) {
                        System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this +
                                "::almacenarObjeto::filasAfectadas: " + filasAfectadas);
                    }
                    return false;
                }
                setContadorModificaciones(contadorModificaciones + filasAfectadas);
            }
        } catch (SQLException sqlEx) {
            if (debug) {
                System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this + "::almacenarObjeto::Excepcion en                        almacenarObjeto: " + sqlEx);
            }
            setErroresDetectados(sqlEx);
            sqlEx.printStackTrace();
            return manejadorExcepcion(objectePersistent, sql.toString(), listParms, sqlEx);
        }
        return true;
    }
    protected boolean creaObjeto(ObjectePersistent objectePersistent) {
        String nombreCampo = null;
        StringBuffer sql = new StringBuffer("INSERT INTO ");
        List listParms = new ArrayList();
        try {
            sql.append(nombreTablaCompleto);
            sql.append(" (");
            for (int i = 1; i <= peticion.getMetadatos().getContadorColumna(); i++) {
                String catalogo = peticion.getMetadatos().getNomCataleg(i);
                String esquema = peticion.getMetadatos().getNomEsquema(i);
                String tabla = peticion.getMetadatos().getNomTaula(i);
                if (modificacionCatalogo != null) {
                    if (!modificacionCatalogo.equals(catalogo)) {
                        continue;
                    }
                }
                if (modificacionEsquema != null) {
                    if (!modificacionEsquema.equals(esquema)) {
                        continue;
                    }
                }
                if (tablaModificada != null) {
                    if (!tablaModificada.equals(tabla)) {
                        continue;
                    }
                }
                String nombreCampoTemp = peticion.getMetadatos().getNomCamp(i);
                if (!peticion.getMetadatos().isGrabable(i) || peticion.getMetadatos().isSolsLectura(i)) {
                    continue;
                }
                String nombreColumna = null;
                if (peticion.isNoNombreColumnaCompleto()) {
                    nombreColumna = peticion.getMetadatos().getNomColumna(i);
                } else {
                    nombreColumna = peticion.getMetadatos().getColumnaNomComplert(i);
                }
                sql.append(nombreColumna).append(", ");
                Object valor = leerValor(objectePersistent, peticion.getMetadatos().getLeerMethod(i));
                listParms.add(valor);
            }
            int idx = sql.lastIndexOf(", ");
            sql = sql.delete(idx, idx + 2);
            sql.append(") VALUES (");
            ListIterator li = listParms.listIterator();
            while (li.hasNext()) {
                Object valor = li.next();
                if (valor == null) {
                    sql.append("NULL, ");
                    li.remove();
                } else {
                    sql.append("?, ");
                }
            }
            idx = sql.lastIndexOf(",");
            sql = sql.delete(idx, idx + 2);
            sql.append(")");
            if (peticion.isGenerarSoloSQL()) {
                if (generadasSQL == null) {
                    generadasSQL = new ArrayList();
                }
                Object[] nota = new Object[2];
                nota[0] = sql.toString();
                nota[1] = listParms.toArray();
                generadasSQL.add(nota);
            } else {
                int filasAfectadas = peticion.getUtilitats().ejecutar(sql.toString(), listParms);
                if (peticion.isThrowFailedInsertException() && filasAfectadas != 1) {
                    throw new SQLException("INSERT INTO " + nombreTablaCompleto + " ha fallado");
                }
                setContadorAltas(contadorAltas + filasAfectadas);
            }
        } catch (SQLException sqlEx) {
            if (debug) {
                System.out.println("lwpf ============ " + new java.util.Date() + " " + this.getClass() + "::" + this + "::creaObjeto::Excepcion en                        creaObjeto: " + sqlEx);
            }
            setErroresDetectados(sqlEx);
            sqlEx.printStackTrace();
            return manejadorExcepcion(objectePersistent, sql.toString(), listParms, sqlEx);
        }
        return true;
    }
    /** Leer la propiedad de contadorBajas.
     * @return Value of property contadorBajas.
     *
     */
    @Override
    public int getContadorBajas() {
        return contadorBajas;
    }
    /** Asignar nueva propiedad a contadorBajas.
     * @param contadorBajas New valor of property contadorBajas.
     *
     */
    protected void setContadorBajas(int contadorBajas) {
        this.contadorBajas = contadorBajas;
    }
    /** Leer la propiedad de contadorAltas.
     * @return Value of property contadorAltas.
     *
     */
    @Override
    public int getContadorAltas() {
        return contadorAltas;
    }
    /** Asignar nueva propiedad a contadorAltas.
     * @param contadorAltas New valor of property contadorAltas.
     *
     */
    protected void setContadorAltas(int contadorAltas) {
        this.contadorAltas = contadorAltas;
    }
    /** Leer la propiedad de contadorModificaciones.
     * @return Value of property contadorModificaciones.
     *
     */
    @Override
    public int getContadorModificaciones() {
        return contadorModificaciones;
    }
    /** Asignar nueva propiedad a contadorModificaciones.
     * @param contadorModificaciones New valor of property contadorModificaciones.
     *
     */
    protected void setContadorModificaciones(int contadorModificaciones) {
        this.contadorModificaciones = contadorModificaciones;
    }
    @Override
    public void reset() {
        contadorBajas = 0;
        contadorAltas = 0;
        contadorModificaciones = 0;
        generadasSQL = null;
        objetosEliminados = null;
        objetosCreados = null;
        objetosModificados = null;
        nombreTablaCompleto = null;
        tablaModificada = null;
        modificacionEsquema = null;
        modificacionCatalogo = null;
        erroresDetectados = null;
    }
    /** Leer la propiedad de generadasSQL.
     * @return Value of property generadasSQL.
     *
     */
    @Override
    public List getSQLGeneradas() {
        return generadasSQL;
    }
    /** Leer la propiedad de erroresDetectados.
     * @return Value of property erroresDetectados.
     *
     */
    @Override
    public Throwable getErroresDetectados() {
        return erroresDetectados;
    }
    /** Asignar nueva propiedad a erroresDetectados.
     * @param erroresDetectados New valor of property erroresDetectados.
     *
     */
    public void setErroresDetectados(Throwable erroresDetectados) {
        this.erroresDetectados = erroresDetectados;
    }
    /** Leer la propiedad de modificacionCatalogo.
     * @return Value of property modificacionCatalogo.
     *
     */
    public String getModificacionCatalogo() {
        return modificacionCatalogo;
    }
    /** Asignar nueva propiedad a modificacionCatalogo.
     * @param modificacionCatalogo New valor of property modificacionCatalogo.
     *
     */
    public void setModificacionCatalogo(String modificacionCatalogo) {
        this.modificacionCatalogo = modificacionCatalogo;
    }
    /** Leer la propiedad de generatedSQLasXML.
     * @return Value of property generatedSQLasXML.
     */
    @Override
    public String getGenerarSentenciasSQLcomoXML() {
        if (this.generadasSQL == null || this.generadasSQL.isEmpty()) {
            return "";
        }
        StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<generated-sql>\n");
        Iterator it = this.generadasSQL.iterator();
        while (it.hasNext()) {
            sb.append(" <sql>\n");
            Object[] objeto = (Object[]) it.next();
            sb.append(" <statement><![CDATA[").append(objeto[0]).append("]]></statement>\n");
            Object[] parametros = (Object[]) objeto[1];
            if (parametros != null && parametros.length > 0) {
                sb.append(" <params>\n");
                for (int i = 0; i < parametros.length; i++) {
                    sb.append(" <param>\n");
                    sb.append(" <value>").append("<![CDATA[").append(parametros[i].toString()).append("]]>").append("</value>\n");
                    sb.append(" <datatype>").append(parametros[i].getClass().getName()).append("</datatype>\n");
                    sb.append(" </param>\n");
                }
                sb.append(" </params>\n");
            }
            sb.append(" </sql>\n");
        }
        sb.append("</generated-sql>\n");
        return sb.toString();
    }
    protected boolean manejadorExcepcion(ObjectePersistent objectePersistent, String sql, Collection colParms, Throwable t) {
        boolean ignorar = false;
        if (t instanceof StringIndexOutOfBoundsException) {
            System.out.println("Asegurese de usar correctametne el esquema (schema) y/o la tabla");
        }
        if (peticion.getManejadorExcepciones() != null) {
            ignorar = peticion.getManejadorExcepciones().lwpfException(objectePersistent, sql, colParms, t);
        }
        return ignorar;
    }
    public boolean isDebug() {
        return debug;
    }
    public void setDebug(boolean debug) {
        this.debug = debug;
    }
    @Override
    public boolean isExcepcionEnObjectListVacios() {
        return excepcionEnObjectListVacio;
    }
    @Override
    public void setExcepcionEnObjectListVacios(boolean excepcionEnObjectListVacio) {
        this.excepcionEnObjectListVacio = excepcionEnObjectListVacio;
    }
    protected Object leerValor(ObjectePersistent objectePersistent, Method metodo) throws SQLException {
        Object valor = null;
        try {
            valor = metodo.invoke(objectePersistent, ARG_LECT_VACIO);
        } catch (Throwable t) {
            if (t instanceof InvocationTargetException) {
                throw new RuntimeException(((InvocationTargetException) t).getTargetException());
            } else {
                throw new RuntimeException(t);
            }
        }
        return valor;
    }

}
